home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Shareware Overload Trio 2
/
Shareware Overload Trio Volume 2 (Chestnut CD-ROM).ISO
/
dir24
/
psi110g.zip
/
MBOXGATE.C
< prev
next >
Wrap
C/C++ Source or Header
|
1994-04-17
|
18KB
|
670 lines
/* The are the GATECMDS functions */
#include <time.h>
#include <ctype.h>
#ifdef MSDOS
#include <alloc.h>
#endif
#ifdef UNIX
#include <sys/types.h>
#include <sys/stat.h>
#endif
#include "global.h"
#include "timer.h"
#include "proc.h"
#include "socket.h"
#include "usock.h"
#include "session.h"
#include "smtp.h"
#include "dirutil.h"
#include "telnet.h"
#include "ftp.h"
#include "ftpserv.h"
#include "commands.h"
#include "netuser.h"
#include "files.h"
#include "bm.h"
#include "pktdrvr.h"
#include "ax25.h"
#include "mailbox.h"
#include "ax25mail.h"
#include "nr4mail.h"
#include "cmdparse.h"
#include "mailfor.h"
/* The dombtelnet(), gw_* functions need to be there if FOQ_CMDS defined
* they are used by dochat() (Operator), and dombfinger commands - WG7J
*/
#if defined GATECMDS || defined FOQ_CMDS
int
dombtelnet(argc,argv,p)
int argc;
char *argv[];
void *p;
{
struct mbx *m;
int s, len, i;
char dsocket[MAXSOCKSIZE];
struct sockaddr_in fsocket;
m = (struct mbx *) p;
fsocket.sin_family = AF_INET;
if(argc < 3)
fsocket.sin_port = IPPORT_TELNET;
else
fsocket.sin_port = atoip(argv[2]);
if((fsocket.sin_addr.s_addr = resolve(argv[1])) == 0){
tprintf(Badhost,argv[1]);
/* Free m->startmsg if set ! - WG7J */
if(m->startmsg != NULLCHAR) {
free(m->startmsg);
m->startmsg = NULLCHAR;
}
return 0;
}
/* Only local telnets to the ttylink port are are allowed
* to the unprivileged user
* If the first letter of the command is 'Q', then it was
* the QUERY command !
*/
if(*argv[0] != 'Q') {
if( !(m->privs & TELNET_CMD) &&
!(ismyaddr(fsocket.sin_addr.s_addr) &&
fsocket.sin_port == IPPORT_TTYLINK) ){
tputs(Noperm);
#ifdef MAILERROR
mail_error("%s: Telnet denied: %s\n",m->name,cmd_line(argc,argv,m->stype));
#endif
/* Free m->starmsg if set ! - WG7J */
/* Shouldn't happen here, but just in case */
if(m->startmsg != NULLCHAR) {
free(m->startmsg);
m->startmsg = NULLCHAR;
}
return 0;
}
}
/* See if we have a route to this address */
if(rt_lookup(fsocket.sin_addr.s_addr) == NULL &&
!ismyaddr(fsocket.sin_addr.s_addr)) {
tprintf("No route to %s!\n",psocket(&fsocket));
return 0;
}
if((s = socket(AF_INET,SOCK_STREAM,0)) == -1){
tputs(Nosock);
/* Free m->starmsg if set ! - WG7J */
if(m->startmsg != NULLCHAR) {
free(m->startmsg);
m->startmsg = NULLCHAR;
}
return 0;
}
#ifdef GWTRACE
log(m->user,"MBOX TELNET: %s to %s:%d",m->name,argv[1],fsocket.sin_port);
#endif
if(fsocket.sin_port == IPPORT_TTYLINK) {
m->startmsg = mallocw(80);
len = MAXSOCKSIZE;
i = getpeername(m->user,dsocket,&len);
sprintf(m->startmsg,"*** Incoming call from %s@%s ***\n",
m->name,i != -1 ? psocket(dsocket): Hostname);
}
m->state = MBX_GATEWAY;
return gw_connect(m,s,(struct sockaddr *)&fsocket,SOCKSIZE);
}
/* Generic mbox gateway code. It sends and frees the contents of m->startmsg
* when the connection has been established unless it a null pointer.
*/
int
gw_connect(m,s,fsocket,len)
struct mbx *m;
int s;
struct sockaddr *fsocket;
int len;
{
int c,timeout;
char *cp, *cp1;
struct proc *child;
struct gwalarm *gwa;
char *node, *tocall, whereto[128], buf[80];
char temp[AXBUF];
struct nrroute_tab *rp;
sockmode(s,SOCK_ASCII);
child = newproc("gw supervisor",256,gw_superv,0,Curproc,m,0);
tputs("Trying...");
if(m->privs & NO_ESCAPE)
tputc('\n');
else {
tputs(" The escape character is: ");
if(m->escape < 32)
tprintf("CTRL-%c\n",m->escape+'A'-1);
else
tprintf("'%c'\n",m->escape);
}
usflush(Curproc->output);
/*find out where we're going to*/
tocall = strdup(psocket(fsocket));
if((cp1 = strchr(tocall,' ')) != NULLCHAR)
*cp1 = '\0';
#if defined GATECMDS && defined NETROM
if(fsocket->sa_family == AF_NETROM) {
/*find the node alias*/
setcall(temp,tocall);
rp = find_nrroute(temp);
node = strdup(rp->alias);
if((cp1 = strchr(node,' ')) != NULLCHAR)
*cp1 = '\0';
sprintf(whereto,"%s:%s",node,tocall);
free(node);
} else
#endif
strcpy(whereto,tocall);
free(tocall);
if(connect(s,(char *)fsocket,len) == -1){
if((cp = sockerr(s)) != NULLCHAR) {
switch(cp[0]) {
case 'R':
sprintf(buf,"%susy from",
(m->family == AF_NETROM)?"B":"*** b");
break;
case 'T':
if(m->family != AF_NETROM) {
sprintf(buf,"*** timeout with");
break;
}
default:
sprintf(buf,"%sailure with",
(m->family == AF_NETROM)?"F":"*** f");
break;
}
tprintf("%s%s %s\n\n",
(m->family == AF_NETROM) ? Mbnrid : "",buf,whereto);
}
shutdown(s,2); /* HB9RWM suggestion */
close_s(s);
killproc(child);
/* Free m->starmsg if set ! - WG7J */
if(m->startmsg != NULLCHAR) {
free(m->startmsg);
m->startmsg = NULLCHAR;
}
return 0;
}
/* The user did not type the escape character */
killproc(child);
tprintf("%s%sonnected to %s\n",
(m->family == AF_NETROM) ? Mbnrid : "",
(m->family == AF_NETROM) ? "C" : "*** c",
whereto);
if(m->startmsg != NULLCHAR){
usputs(s,m->startmsg);
free(m->startmsg);
m->startmsg = NULLCHAR;
}
/* Since NOS does not flush the output socket after a certain
* period of time, we have to arrange that ourselves.
*/
gwa = (struct gwalarm *) mallocw(sizeof(struct gwalarm));
gwa->s1 = Curproc->output;
gwa->s2 = s;
set_timer(&gwa->t,2*1000L);
gwa->t.func = gw_alarm;
gwa->t.arg = (void *) gwa;
start_timer(&gwa->t);
/* Fork off the receive process */
child = newproc("gw in",1024,gw_input,s,m,Curproc,0);
timeout = 0;
for(;;){
alarm(Mbtdiscinit*1000L);
if((c = recvchar(Curproc->input)) == EOF) {
timeout = (errno == EALARM);
break;
}
alarm(0L);
/* Only check ESCAPE char if that is currently turned on */
if( !(m->privs & NO_ESCAPE) && c == m->escape){
if(socklen(Curproc->input,0))
recv_mbuf(Curproc->input,NULL,0,NULLCHAR,0);
break;
}
if(usputc(s,c) == EOF)
break;
}
stop_timer(&gwa->t);
free((char *)gwa);
close_s(s);
killproc(child); /* get rid of the receive process */
if(m->family == AF_INET)
tprintf("%c%c%c\n",IAC,WONT,TN_ECHO);
if(timeout)
return EOF;
return 0;
}
void
gw_input(s,notused,p)
int s;
void *notused;
void *p;
{
int c;
struct proc *parent;
struct mbx *m;
char *cp, *cp1;
char response[4];
parent = (struct proc *) p;
m = (struct mbx *) notused;
cp1 = strdup(Mbnrid);
if((cp = strchr(cp1,'}')) != NULLCHAR)
*cp = '\0';
strupr(cp1);
#ifdef notdef
while((c = recvchar(s)) != EOF)
tputc(c);
#endif
while((c = recvchar(s)) != EOF){
if(c != IAC){
tputc((char)c);
continue;
}
/* IAC received, get command sequence */
c = recvchar(s);
switch(c){
case WILL:
response[0] = IAC;
response[1] = DONT;
response[2] = recvchar(s);
response[3] = '\0';
usputs(s,response);
break;
case WONT:
case DONT:
c = recvchar(s);
break;
case DO:
response[0] = IAC;
response[1] = WONT;
response[2] = recvchar(s);
response[3] = '\0';
usputs(s,response);
break;
case IAC: /* Escaped IAC */
usputc(s,IAC);
break;
}
}
if((cp = sockerr(s)) != NULLCHAR && m->family != AF_NETROM) {
switch(cp[0]) {
case 'T':
usprintf(m->user,"\n*** %s: Link failure",cp1);
break;
case 'R':
usputs(m->user,"*** DM received");
break;
}
}
usprintf(m->user,"\n%s%seconnected to %s\n\n",
(m->family == AF_NETROM) ? Mbnrid : "",
(m->family == AF_NETROM) ? "R" : "*** r",
cp1);
free(cp1);
cp1 = NULLCHAR;
/* Tell the parent that we are no longer connected */
alert(parent,ENOTCONN);
pwait(Curproc); /* Now wait to be killed */
}
/* Check if the escape character is typed while the parent process is busy
* doing other things.
*/
void
gw_superv(null,proc,p)
int null;
void *proc;
void *p;
{
struct proc *parent;
struct mbx *m;
int c;
parent = (struct proc *) proc;
m = (struct mbx *) p;
while((c = recvchar(Curproc->input)) != EOF)
if(c == m->escape){
/* flush anything in the input queue */
if(socklen(Curproc->input,0))
recv_mbuf(Curproc->input,NULL,0,NULLCHAR,0);
break;
}
alert(parent,EINTR); /* Tell the parent to quit */
pwait(Curproc); /* Please kill me */
}
void
gw_alarm(p)
void *p;
{
struct gwalarm *gwa = (struct gwalarm *)p;
char oldbl;
struct usock *up;
/* Flush sockets s1 and s2, but first make sure that the socket
* is set to non-blocking mode, to prevent the flush from blocking
* if the high water mark has been reached.
*/
if((up = itop(gwa->s1)) != NULLUSOCK) {
oldbl = up->noblock;
up->noblock = 1;
usflush(gwa->s1);
up->noblock = oldbl;
}
if((up = itop(gwa->s2)) != NULLUSOCK) {
oldbl = up->noblock;
up->noblock = 1;
usflush(gwa->s2);
up->noblock = oldbl;
}
start_timer(&gwa->t);
}
#endif /* GATECMDS || FOQ_CMDS */
#ifdef GATECMDS
/*Enlighten them a bit!
*/
static char Mbconnecthelp[] =
"Syntax:\n"
#ifdef NETROM
"'C <node>' for NET/ROM connects\n"
#endif
#ifdef AX25
"'C <port> <call>' for AX.25 connects\n"
#endif
#ifdef CONVERS
"'CONV [channel]' to access conference bridge\n"
#endif
"\n";
#ifdef NETROM
int
dombnrneighbour(argc,argv,p)
int argc;
char *argv[];
void *p;
{
struct mbx *m;
m = (struct mbx *)p;
if(!(m->privs & NETROM_CMD)) {
tputs(Noperm);
return 0;
}
return donrneighbour(argc,argv,NULL);
}
int
dombnrnodes(argc,argv,p)
int argc;
char *argv[];
void *p;
{
struct mbx *m;
m = (struct mbx *)p;
if(!(m->privs & NETROM_CMD)) {
tputs(Noperm);
return 0;
}
if(argc < 2)
return doroutedump();
if(*argv[1] == '*')
argc = 1;
return dorouteinfo(argc,argv,p);
}
#endif /* NETROM */
int
dombescape(argc,argv,p)
int argc;
char *argv[];
void *p;
{
struct mbx *m;
m = (struct mbx *)p;
if(argc < 2){
tprintf("Escape is %s, Escape char: ",
(m->privs & NO_ESCAPE) ? "OFF" : "ON");
if(m->escape < 32)
tprintf("CTRL-%c\n",m->escape+'A'-1);
else
tprintf("'%c'\n",m->escape);
return 0;
}
if(strlen(argv[1]) > 1) {
if(isdigit(*argv[1]))
m->escape = (char) atoi(argv[1]);
else {
if( !strnicmp(argv[1],"OFF",3) || !strnicmp(argv[1],"dis",3) )
m->privs |= NO_ESCAPE;
else
m->privs &= ~NO_ESCAPE;
}
} else
m->escape = *argv[1];
return 0;
}
int
dombconnect(argc,argv,p)
int argc;
char *argv[];
void *p;
{
struct mbx *m;
struct nrroute_tab *np;
int ndigis,i,s;
struct sockaddr_nr lsocket,fsocket;
struct sockaddr_ax alsocket; /*the local socket*/
struct sockaddr_ax afsocket; /*the remote socket*/
struct iface *ifp;
char alias[AXBUF];
char local_call[AXALEN];
char digis[MAXDIGIS][AXALEN];
char target[AXALEN];
m = (struct mbx *) p;
if(argc == 1){
tputs(Mbconnecthelp);
return 0;
}
if(MBSecure)
#ifdef NETROM
if((m->family != AF_AX25) && (m->family != AF_NETROM)) {
#else
if(m->family != AF_AX25) {
#endif
tputs(Noperm);
#ifdef MAILERROR
mail_error("%s: gateway denied (secure mode): %s\n",m->name,cmd_line(argc,argv,m->stype));
#endif
return 0;
}
if (argc == 2) {
#ifndef NETROM
tputs(Mbconnecthelp);
return 0;
}
#else
/*NETROM connection wanted*/
if(!(m->privs & NETROM_CMD)) {
tputs(Noperm);
#ifdef MAILERROR
mail_error("%s: NETROM gate to %s denied\n",m->name,argv[1]);
#endif
return 0;
}
if(Nr_iface == NULLIF){
tputs("NET/ROM not activated.\n\n");
return 0;
}
/* See if the requested destination is a known alias or call,
* use it if it is. Otherwize give an error message.
*/
putalias(alias,argv[1],0);
strupr(argv[1]); /*make sure it's upper case*/
if((np = find_nrboth(alias,argv[1])) == NULLNRRTAB){
/*no such call or node alias*/
tputs("no such node\n\n");
tputs(Mbconnecthelp);
dombports(0,NULL,p);
return 0;
}
if((s = socket(AF_NETROM,SOCK_SEQPACKET,0)) == -1){
tputs(Nosock);
return 0;
}
#ifdef GWTRACE
log(m->user,"MBOX NETROM: %s to %s",m->name,argv[1]);
#endif
lsocket.nr_family = AF_NETROM;
/* Set up our local username, bind would use Mycall instead */
memcpy(lsocket.nr_addr.user,m->call,AXALEN);
/* Set up our source address */
memcpy(lsocket.nr_addr.node,Nr_iface->hwaddr,AXALEN);
bind(s,(char *)&lsocket,sizeof(struct sockaddr_nr));
memcpy(fsocket.nr_addr.user,np->call,AXALEN);
memcpy(fsocket.nr_addr.node,np->call,AXALEN);
fsocket.nr_family = AF_NETROM;
m->state = MBX_GATEWAY;
return gw_connect(m,s,(struct sockaddr *)&fsocket, sizeof(struct sockaddr_nr));
}
#endif /*NETROM*/
#ifdef AX25
if(argc > 2) {
/*AX25 gateway connection wanted*/
if(!(m->privs & AX25_CMD)) {
tputs(Noperm);
#ifdef MAILERROR
mail_error("%s: AX.25 gate to %s on %s denied\n",m->name,argv[2],argv[1]);
#endif
return 0;
}
if( ((ifp = if_lookup(argv[1])) == NULLIF) ||
((ifp->flags & HIDE_PORT) && !(m->privs & SYSOP_CMD)) ||
(ifp->type != CL_AX25) ) {
tprintf("Unknown port %s\n",argv[1]);
dombports(0,NULL,p);
return 0;
}
if(setcall(target,argv[2]) == -1){
tprintf("Bad call %s\n",argv[2]);
return 0;
}
/* If digipeaters are given, put them in the routing table */
if(argc > 3){
ndigis = argc - 3;
if(ndigis > MAXDIGIS){
tputs("Too many digipeaters\n");
return 0;
}
for(i=0;i<ndigis;i++){
if(setcall(digis[i],argv[i+3]) == -1){
tprintf("Bad digipeater %s\n",argv[i+3]);
return 0;
}
}
if(ax_add(target,AX_AUTO,digis,ndigis,ifp) == NULLAXR){
tputs("AX25 route add failed\n");
return 0;
}
}
if((s = socket(AF_AX25,SOCK_STREAM,0)) == -1){
tputs(Nosock);
return 0;
}
#ifdef GWTRACE
log(m->user,"MBOX AX25: %s to %s on %s",m->name,argv[2],argv[1]);
#endif
/*fill in the known stuff*/
alsocket.sax_family = afsocket.sax_family= AF_AX25;
/*the remote call to connect to*/
setcall(afsocket.ax25_addr,argv[2]);
/*the outgoing interface*/
strncpy(afsocket.iface,argv[1],ILEN);
/*now set local user call, invert ssid*/
memcpy(local_call,m->call,AXALEN);
local_call[AXALEN-1] ^= 0x1e;
memcpy(alsocket.ax25_addr,local_call,AXALEN);
/*and bind it (otherwize Mycall will be used!)*/
bind(s,(char *)&alsocket,sizeof(struct sockaddr_ax));
m->state = MBX_GATEWAY;
return gw_connect(m,s,(struct sockaddr *)&afsocket, sizeof(struct sockaddr_ax));
}
#endif /* AX25 */
return 0;
}
#ifdef AX25
int
dombports(argc,argv,p)
int argc;
char *argv[];
void *p;
{
struct iface *ifp;
struct mbx *m = (struct mbx *)p;
if(m->privs & NO_LISTS) {
tputs(Noperm);
return 0;
}
tputs("Available ports:\n");
for(ifp=Ifaces;ifp!=NULLIF;ifp=ifp->next)
if(ifp->type == CL_AX25 && \
(!(ifp->flags & HIDE_PORT) || (m->privs & SYSOP_CMD)) ) {
tprintf("%-7s",ifp->name);
if(ifp->descr != NULLCHAR)
tprintf(": %s",ifp->descr);
else
tputc('\n');
}
tputc('\n');
return 0;
}
#endif /* AX25 */
#endif /* GATECMDS */